<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { ChevronDown } from 'lucide-vue-next'

interface SelectOption {
  value: string
  label: string
  disabled?: boolean
}

interface Props {
  modelValue?: string
  options: SelectOption[]
  placeholder?: string
  class?: string
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  placeholder: 'Select an option',
  disabled: false
})

const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()

const isOpen = ref(false)
const triggerRef = ref<HTMLDivElement | null>(null)
const dropdownRef = ref<HTMLDivElement | null>(null)

const selectedOption = computed(() => {
  return props.options.find(opt => opt.value === props.modelValue)
})

const displayText = computed(() => {
  return selectedOption.value?.label || props.placeholder
})

function toggleDropdown() {
  if (props.disabled) return
  isOpen.value = !isOpen.value
}

function selectOption(option: SelectOption) {
  if (option.disabled) return
  emit('update:modelValue', option.value)
  isOpen.value = false
}

function handleClickOutside(event: MouseEvent) {
  if (
    triggerRef.value &&
    dropdownRef.value &&
    !triggerRef.value.contains(event.target as Node) &&
    !dropdownRef.value.contains(event.target as Node)
  ) {
    isOpen.value = false
  }
}

onMounted(() => {
  document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside)
})
</script>

<template>
  <div class="select-wrapper" :class="{ disabled }">
    <div
      ref="triggerRef"
      class="select-trigger"
      :class="{ open: isOpen, disabled, 'has-value': modelValue }"
      @click="toggleDropdown"
    >
      <span class="select-value">{{ displayText }}</span>
      <ChevronDown class="select-icon" :class="{ rotate: isOpen }" />
    </div>
    
    <Teleport to="body">
      <Transition name="dropdown">
        <div
          v-if="isOpen"
          ref="dropdownRef"
          class="select-dropdown"
          :style="{
            top: triggerRef ? `${triggerRef.getBoundingClientRect().bottom + 8}px` : '0',
            left: triggerRef ? `${triggerRef.getBoundingClientRect().left}px` : '0',
            minWidth: triggerRef ? `${triggerRef.getBoundingClientRect().width}px` : 'auto'
          }"
        >
          <div class="select-options">
            <div
              v-for="option in options"
              :key="option.value"
              class="select-option"
              :class="{
                selected: option.value === modelValue,
                disabled: option.disabled
              }"
              @click="selectOption(option)"
            >
              <span class="option-label">{{ option.label }}</span>
              <svg
                v-if="option.value === modelValue"
                class="option-check"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
              >
                <polyline points="20 6 9 17 4 12"></polyline>
              </svg>
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>
  </div>
</template>

<style scoped>
.select-wrapper {
  position: relative;
  width: 100%;
}

.select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 2.25rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
  border: 0.5px solid rgba(0, 0, 0, 0.12);
  background-color: white;
  box-shadow: 
    0 1px 2px rgba(0, 0, 0, 0.08),
    0 0 0 0.5px rgba(255, 255, 255, 0.5) inset;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

.select-trigger:hover:not(.disabled) {
  border-color: rgba(0, 0, 0, 0.18);
  box-shadow: 
    0 2px 4px rgba(0, 0, 0, 0.1),
    0 0 0 0.5px rgba(255, 255, 255, 0.6) inset;
}

.select-trigger.open,
.select-trigger:focus {
  border-color: #0A84FF;
  box-shadow: 
    0 0 0 3px rgba(10, 132, 255, 0.15),
    0 2px 4px rgba(0, 0, 0, 0.1),
    0 0 0 0.5px #0A84FF inset;
}

.select-trigger.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.select-value {
  flex: 1;
  font-size: 0.875rem;
  font-weight: 500;
  color: #1d1d1f;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.select-trigger:not(.has-value) .select-value {
  color: #86868b;
  font-weight: 400;
}

.select-icon {
  width: 1rem;
  height: 1rem;
  color: #86868b;
  flex-shrink: 0;
  margin-left: 0.5rem;
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.select-icon.rotate {
  transform: rotate(180deg);
}

.select-dropdown {
  position: fixed;
  z-index: 9999;
  margin-top: 0;
  border-radius: 1rem;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 0.5px solid rgba(0, 0, 0, 0.08);
  box-shadow: 
    0 16px 48px rgba(0, 0, 0, 0.15),
    0 4px 16px rgba(0, 0, 0, 0.1),
    0 0 0 0.5px rgba(255, 255, 255, 0.5) inset;
  overflow: hidden;
  max-height: 24rem;
}

.select-options {
  padding: 0.5rem;
  max-height: 24rem;
  overflow-y: auto;
}

.select-options::-webkit-scrollbar {
  width: 8px;
}

.select-options::-webkit-scrollbar-track {
  background: transparent;
}

.select-options::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 4px;
}

.select-options::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.3);
}

.select-option {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  padding-right: 2.25rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: #1d1d1f;
  cursor: pointer;
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  user-select: none;
}

.select-option:hover:not(.disabled) {
  background: rgba(120, 120, 128, 0.12);
}

.select-option.selected {
  background: linear-gradient(180deg, #0A84FF 0%, #0066D6 100%);
  color: white;
  font-weight: 600;
  box-shadow: 
    0 2px 6px rgba(10, 132, 255, 0.3),
    0 1px 2px rgba(0, 0, 0, 0.1);
}

.select-option.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.option-label {
  flex: 1;
}

.option-check {
  position: absolute;
  right: 0.5rem;
  width: 1rem;
  height: 1rem;
  stroke-width: 3;
}

/* 暗黑模式 */
html.dark-mode .select-trigger {
  background-color: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.1);
}

html.dark-mode .select-trigger:hover:not(.disabled) {
  border-color: rgba(255, 255, 255, 0.18);
}

html.dark-mode .select-value {
  color: #f5f5f7;
}

html.dark-mode .select-trigger:not(.has-value) .select-value {
  color: #98989d;
}

html.dark-mode .select-dropdown {
  background: rgba(40, 40, 42, 0.92);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border-color: rgba(255, 255, 255, 0.1);
  box-shadow: 
    0 16px 48px rgba(0, 0, 0, 0.4),
    0 4px 16px rgba(0, 0, 0, 0.3),
    0 0 0 0.5px rgba(255, 255, 255, 0.1) inset;
}

html.dark-mode .select-option {
  color: #f5f5f7;
}

html.dark-mode .select-option:hover:not(.disabled) {
  background: rgba(120, 120, 128, 0.18);
}

html.dark-mode .select-options::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.2);
}

html.dark-mode .select-options::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.3);
}

/* 动画 */
.dropdown-enter-active {
  animation: dropdown-in 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.dropdown-leave-active {
  animation: dropdown-out 0.15s cubic-bezier(0.4, 0, 1, 1);
}

@keyframes dropdown-in {
  from {
    opacity: 0;
    transform: scale(0.95) translateY(-4px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes dropdown-out {
  from {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
  to {
    opacity: 0;
    transform: scale(0.95) translateY(-4px);
  }
}
</style>
